home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Programming / jikes-1.02 / src / bytecode.h < prev    next >
Encoding:
C/C++ Source or Header  |  1999-08-26  |  26.6 KB  |  810 lines

  1. // $Id: bytecode.h,v 1.13 1999/08/26 15:34:03 shields Exp $
  2. //
  3. // License Agreement available at the following URL:
  4. // http://www.ibm.com/research/jikes.
  5. // Copyright (C) 1996, 1998, International Business Machines Corporation
  6. // and others.  All Rights Reserved.
  7. // You must accept the terms of that agreement to use this software.
  8.  
  9. //
  10. #ifndef bytecode_INCLUDED
  11. #define bytecode_INCLUDED
  12.  
  13. #include <stdio.h>
  14. #include "tuple.h"
  15. #include "ast.h"
  16. #include "class.h"
  17. #include "option.h"
  18. #include "long.h"
  19. #include "op.h"
  20. #include "segment.h"
  21.  
  22. class TypeSymbol;
  23. class Control;
  24. class Semantic;
  25.  
  26. class LabelUse
  27. {
  28. public:
  29.     int use_length, // length of use (2 or 4 bytes)
  30.         op_offset,  // length of use from opcode starting instruction
  31.         use_offset; // offset in code stream of use
  32.  
  33.     LabelUse() : use_length(0), op_offset(0), use_offset(0) {}
  34.  
  35.     LabelUse(int _length, int _op_offset, int _use) : use_length(_length), op_offset(_op_offset), use_offset(_use) {}
  36. };
  37.  
  38.  
  39. class Label
  40. {
  41. public:
  42.     bool defined;    // boolean, set when value is known
  43.     int definition; // offset of definition point of label
  44.     Tuple<LabelUse> uses;
  45.  
  46.     Label() : defined(false), definition(0) {}
  47. };
  48.  
  49.  
  50. class ByteCode : public ClassFile, public StringConstant, public Operators
  51. {
  52.     Control& this_control;
  53.     Semantic& this_semantic;
  54.  
  55.     void CompileClass();
  56.     void CompileInterface();
  57.  
  58.     int line_number,
  59.         last_label_pc,        // pc for last (closest to end) label
  60.         last_op_pc,           // pc of last operation emitted
  61.         last_op_nop,          // set if last operation was NOP.
  62.         this_block_depth,     // depth of current block
  63.         stack_depth,          // current stack depth;
  64.         max_stack,
  65.         max_block_depth,
  66.         last_parameter_index; // set to local variable index of last parameter
  67.  
  68.     bool string_overflow,
  69.          library_method_not_found;
  70.  
  71.     Code_attribute *code_attribute; // code for current method ?
  72.     LineNumberTable_attribute *line_number_table_attribute;
  73.     LocalVariableTable_attribute *local_variable_table_attribute;
  74.     InnerClasses_attribute *inner_classes_attribute;
  75.  
  76.     void MethodInitialization()
  77.     {
  78.         last_label_pc = 0;
  79.         last_op_pc = 0;
  80.         last_op_nop = 0;
  81.         this_block_depth = 0;
  82.  
  83.         stack_depth = 0;
  84.  
  85.         max_stack = 0;
  86.  
  87.         return;
  88.     }
  89.  
  90.     Label *begin_labels,
  91.           *break_labels,
  92.           *continue_labels,
  93.           *final_labels,
  94.           *monitor_labels,
  95.           *test_labels;
  96.  
  97.     int *has_finally_clause;
  98.     bool *is_synchronized;
  99.  
  100.     BlockSymbol **block_symbols; // block symbols for current block
  101.  
  102.     int synchronized_blocks, // number of outstanding synchronized blocks
  103.         finally_blocks,      // number of outstanding synchronized blocks
  104.         block_depth;             // need to reset at start of each method
  105.     TypeSymbol *method_type;     // return type of method being compiled
  106.  
  107.     void AllocateMethodInfo(int max_block_depth_)
  108.     {
  109.         max_block_depth = max_block_depth_;
  110.  
  111.         begin_labels = new Label[max_block_depth + 1];
  112.         break_labels = new Label[max_block_depth + 1];
  113.         continue_labels = new Label[max_block_depth + 1];
  114.         final_labels = new Label[max_block_depth + 1];
  115.         monitor_labels = new Label[max_block_depth + 1];
  116.         test_labels = new Label[max_block_depth + 1];
  117.  
  118.         has_finally_clause = new int[max_block_depth + 1];
  119.         is_synchronized = new bool[max_block_depth + 1];
  120.         for (int i = 0; i < max_block_depth; i++)
  121.         {
  122.             has_finally_clause[i] = 0;  // reset has_finally_clause
  123.             is_synchronized[i] = false; // reset is_synchronized
  124.         }
  125.  
  126.         block_symbols = new BlockSymbol *[max_block_depth+1];
  127.  
  128.         return;
  129.     }
  130.  
  131.     void FreeMethodInfo()
  132.     {
  133.         delete [] begin_labels;
  134.         delete [] break_labels;
  135.         delete [] continue_labels;
  136.         delete [] final_labels;
  137.         delete [] monitor_labels;
  138.         delete [] test_labels;
  139.  
  140.         delete [] has_finally_clause;
  141.         delete [] is_synchronized;
  142.  
  143.         delete [] block_symbols;
  144.  
  145.         return;
  146.     }
  147.  
  148.     void    ProcessAbruptExit(int);
  149.     void    CompleteLabel(Label &lab);
  150.     void    DefineLabel(Label &lab);
  151.     void    UseLabel(Label &lab, int length, int op_offset);
  152.  
  153.     bool IsLabelUsed(Label &lab)
  154.     {
  155.         return (lab.uses.Length() > 0);
  156.     }
  157.  
  158.  
  159.     //
  160.     // see if operand is null. The front-end will have inserted a cast
  161.     // of null to the present type
  162.     //
  163.     bool IsNull(AstExpression *p)
  164.     {
  165.         return (p -> CastExpressionCast() ? (p -> CastExpressionCast() -> expression -> Type() == this_control.null_type) : false);
  166.     }
  167.  
  168.  
  169.     //
  170.     // Does p refer to a non-null reference type?
  171.     //
  172.     bool IsReferenceType(TypeSymbol *p)
  173.     {
  174.         return (! (p -> Primitive() || p == this_control.null_type));
  175.     }
  176.  
  177.  
  178.     //
  179.     // see if operand is integer type and is zero
  180.     //
  181.     bool IsZero(AstExpression *p)
  182.     {
  183.         if (p -> IsConstant() && (p -> Type() == this_control.int_type || p -> Type() == this_control.boolean_type))
  184.         {
  185.             IntLiteralValue *vp = (IntLiteralValue *) (p -> value);
  186.             return (vp -> value == 0);
  187.         }
  188.  
  189.         return false;
  190.     }
  191.  
  192.  
  193.     //
  194.     // memory access: reference either
  195.     // constant (literal)
  196.     // name (includes local varable, or class variable, or field access)
  197.     // array
  198.     //
  199.     enum
  200.     {
  201.         LHS_LOCAL =  0, // local variable
  202.         LHS_ARRAY =  1, // array (of any kind)
  203.         LHS_FIELD =  2, // instance variable
  204.         LHS_STATIC = 3, // class variable
  205.         LHS_METHOD = 4 // access to private variable
  206.     };
  207.  
  208.     int GetLhsKind(AstExpression *expression)
  209.     {
  210.         AstAssignmentExpression *assignment = expression -> AssignmentExpressionCast();
  211.         AstPreUnaryExpression *pre = expression -> PreUnaryExpressionCast();
  212.         AstPostUnaryExpression *post = expression -> PostUnaryExpressionCast();
  213.  
  214.         AstExpression *lhs = assignment ? (assignment -> write_method ? (AstExpression *) NULL : assignment -> left_hand_side)
  215.                                         : pre ? (pre -> write_method ? (AstExpression *) NULL : pre -> expression)
  216.                                               : post ? (post -> write_method ? (AstExpression *) NULL : post -> expression)
  217.                                                      : expression;
  218.  
  219.         //
  220.         // Find symbol that is associated with expression. If the subexpression has
  221.         // to be referenced via an access method then the symbol is null
  222.         //
  223.         AstCastExpression *cast = (lhs ? lhs -> CastExpressionCast() : (AstCastExpression *) NULL);
  224.         Symbol *sym = cast ? cast -> expression -> symbol : (lhs ? lhs -> symbol : (Symbol *) NULL);
  225.  
  226.         //
  227.         // If the expression associated with the left-hand side is null,
  228.         // then we have an access method.
  229.         // Otherwise, a left-hand side is either an array access,
  230.         // a field access or a name. In the case of a FieldAccess
  231.         // or name, the left-hand side is resolved into a variable.
  232.         // In the case of an array access, it is resolved into a type.
  233.         //
  234.         VariableSymbol *var = (sym ? sym -> VariableCast() : (VariableSymbol *) NULL);
  235.         return ((! lhs) ? LHS_METHOD
  236.                         : (! var) ? LHS_ARRAY
  237.                                   : var -> owner -> MethodCast() ? LHS_LOCAL
  238.                                                                  : var -> ACC_STATIC() ? LHS_STATIC
  239.                                                                                        : LHS_FIELD);
  240.     }
  241.  
  242.  
  243.     int GetTypeWords(TypeSymbol *type)
  244.     {
  245.         return this_control.IsDoubleWordType(type) ? 2 : 1;
  246.     }
  247.  
  248.  
  249.     //
  250.     // methods to load and store values
  251.     //
  252.     void LoadLocal(int varno, TypeSymbol *);
  253.     void StoreLocalVariable(VariableSymbol *);
  254.     void StoreLocal(int varno, TypeSymbol *);
  255.     void LoadReference(AstExpression *);
  256.     void LoadLiteral(LiteralValue *, TypeSymbol *);
  257.     void LoadImmediateInteger(int);
  258.     int  LoadVariable(int, AstExpression *);
  259.     int  LoadArrayElement(TypeSymbol *);
  260.     void StoreArrayElement(TypeSymbol *);
  261.     void StoreField(AstExpression *);
  262.     void StoreVariable(int, AstExpression *);
  263.  
  264.     void LoadConstantAtIndex(u2 index)
  265.     {
  266.         if (index <= 255)
  267.         {
  268.             PutOp(OP_LDC);
  269.             PutU1((u1) index);
  270.         }
  271.         else
  272.         {
  273.             PutOp(OP_LDC_W);
  274.             PutU2(index);
  275.         }
  276.  
  277.         return;
  278.     }
  279.  
  280.     //
  281.     // These pools are sets that keep track of elements that have
  282.     // already been inserted in the constant pool.
  283.     //
  284.     SegmentPool segment_pool;
  285.  
  286.     Pair *double_constant_pool_index,
  287.          *integer_constant_pool_index,
  288.          *long_constant_pool_index,
  289.          *float_constant_pool_index,
  290.          *string_constant_pool_index,
  291.  
  292.          utf8_constant_pool_index,
  293.          class_constant_pool_index;
  294.  
  295.     Triplet *name_and_type_constant_pool_index,
  296.             *fieldref_constant_pool_index,
  297.             *methodref_constant_pool_index;
  298.  
  299.     u2 RegisterNameAndType(Utf8LiteralValue *name, Utf8LiteralValue *type_name)
  300.     {
  301.         assert((name != NULL && type_name != NULL) && "null argument to RegisterNameAndType");
  302.  
  303.         if (! name_and_type_constant_pool_index)
  304.             name_and_type_constant_pool_index = new Triplet(segment_pool, this_control.Utf8_pool.symbol_pool.Length());
  305.  
  306.         u2 index = name_and_type_constant_pool_index -> Image(name -> index, type_name -> index);
  307.         if (index == 0)
  308.         {
  309.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  310.             index = i;
  311.             name_and_type_constant_pool_index -> Image(name -> index, type_name -> index) = index;
  312.             constant_pool[i] = new CONSTANT_NameAndType_info(CONSTANT_NameAndType, RegisterUtf8(name), RegisterUtf8(type_name));
  313.         }
  314.  
  315.         return index;
  316.     }
  317.  
  318.  
  319.     u2 RegisterFieldref(Utf8LiteralValue *class_name,
  320.                         Utf8LiteralValue *field_name,
  321.                         Utf8LiteralValue *field_type_name)
  322.     {
  323.         assert((class_name != NULL && field_name != NULL && field_type_name != NULL) && "null argument to RegisterFieldref");
  324.  
  325.         if (! fieldref_constant_pool_index)
  326.             fieldref_constant_pool_index = new Triplet(segment_pool, this_control.Utf8_pool.symbol_pool.Length());
  327.  
  328.         u2 name_type_index = RegisterNameAndType(field_name, field_type_name),
  329.            index = fieldref_constant_pool_index -> Image(class_name -> index, name_type_index);
  330.         if (index == 0)
  331.         {
  332.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  333.             index = i;
  334.             fieldref_constant_pool_index -> Image(class_name -> index, name_type_index) = index;
  335.             constant_pool[i] = new CONSTANT_Fieldref_info(CONSTANT_Fieldref, RegisterClass(class_name), name_type_index);
  336.         }
  337.  
  338.         return index;
  339.     }
  340.  
  341.  
  342.     u2 RegisterFieldref(TypeSymbol *type, VariableSymbol *variable_symbol)
  343.     {
  344.         assert(variable_symbol -> owner -> TypeCast());
  345.  
  346.         return RegisterFieldref(type -> fully_qualified_name,
  347.                                 variable_symbol -> ExternalIdentity() -> Utf8_literal,
  348.                                 variable_symbol -> Type() -> signature);
  349.     }
  350.  
  351.  
  352.     u2 RegisterFieldref(VariableSymbol *variable_symbol)
  353.     {
  354.         assert(variable_symbol -> owner -> TypeCast());
  355.  
  356.         return RegisterFieldref(variable_symbol -> owner -> TypeCast() -> fully_qualified_name,
  357.                                 variable_symbol -> ExternalIdentity() -> Utf8_literal,
  358.                                 variable_symbol -> Type() -> signature);
  359.     }
  360.  
  361.  
  362.     u2 RegisterMethodref(ConstantKind kind,
  363.                          Utf8LiteralValue *class_name,
  364.                          Utf8LiteralValue *method_name,
  365.                          Utf8LiteralValue *method_type_name)
  366.     {
  367.         assert((class_name != NULL && method_name != NULL && method_type_name != NULL) && "null argument to RegisterMethodref");
  368.  
  369.         if (! methodref_constant_pool_index)
  370.             methodref_constant_pool_index = new Triplet(segment_pool, this_control.Utf8_pool.symbol_pool.Length());
  371.  
  372.         u2 name_type_index = RegisterNameAndType(method_name, method_type_name),
  373.            index = methodref_constant_pool_index -> Image(class_name -> index, name_type_index);
  374.         if (index == 0)
  375.         {
  376.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  377.             index = i;
  378.             methodref_constant_pool_index -> Image(class_name -> index, name_type_index) = index;
  379.  
  380.             u2 class_name_index = RegisterClass(class_name);
  381.             constant_pool[i] = (kind == CONSTANT_Methodref
  382.                                       ? (cp_info *) new CONSTANT_Methodref_info(CONSTANT_Methodref,
  383.                                                                                 class_name_index,
  384.                                                                                 name_type_index)
  385.                                       : (cp_info *) new CONSTANT_InterfaceMethodref_info(CONSTANT_InterfaceMethodref,
  386.                                                                                          class_name_index,
  387.                                                                                          name_type_index));
  388.         }
  389.  
  390.         return index;
  391.     }
  392.  
  393.  
  394.     u2 RegisterMethodref(Utf8LiteralValue *class_name, Utf8LiteralValue *method_name, Utf8LiteralValue *method_type_name)
  395.     {
  396.         return RegisterMethodref(CONSTANT_Methodref, class_name, method_name, method_type_name);
  397.     }
  398.  
  399.     u2 RegisterInterfaceMethodref(Utf8LiteralValue *class_name, Utf8LiteralValue *method_name, Utf8LiteralValue *method_type_name)
  400.     {
  401.         return RegisterMethodref(CONSTANT_InterfaceMethodref, class_name, method_name, method_type_name);
  402.     }
  403.  
  404.  
  405.     u2 RegisterLibraryMethodref(MethodSymbol *method)
  406.     {
  407.         if (method) // The library method must exist. If it is not, flag an error.
  408.             return RegisterMethodref(CONSTANT_Methodref, method -> containing_type -> fully_qualified_name,
  409.                                                          method -> ExternalIdentity()-> Utf8_literal,
  410.                                                          method -> signature);
  411.         library_method_not_found = true;
  412.  
  413.         return 0;
  414.     }
  415.  
  416.     u2 RegisterDouble(DoubleLiteralValue *lit)
  417.     {
  418.         assert((lit != NULL) && "null argument to RegisterDouble");
  419.  
  420.         if (! double_constant_pool_index)
  421.             double_constant_pool_index = new Pair(segment_pool, this_control.double_pool.symbol_pool.Length());
  422.  
  423.         u2 index = (*double_constant_pool_index)[lit -> index];
  424.         if (index == 0)
  425.         {
  426.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  427.             constant_pool.Next() = NULL;       // extra slop for double-word entry
  428.             index = i;
  429.             (*double_constant_pool_index)[lit -> index] = index;
  430.             constant_pool[i] = new CONSTANT_Double_info(CONSTANT_Double, lit -> value.HighWord(), lit -> value.LowWord());
  431.         }
  432.  
  433.         return index;
  434.     }
  435.  
  436.  
  437.     u2 RegisterInteger(IntLiteralValue *lit)
  438.     {
  439.         assert((lit != NULL) && "null argument to RegisterInteger");
  440.  
  441.         if (! integer_constant_pool_index)
  442.             integer_constant_pool_index = new Pair(segment_pool, this_control.int_pool.symbol_pool.Length());
  443.  
  444.         u2 index = (*integer_constant_pool_index)[lit -> index];
  445.         if (index == 0)
  446.         {
  447.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  448.             index = i;
  449.             (*integer_constant_pool_index)[lit -> index] = index;
  450.             int val = lit -> value;
  451.             u4 bytes = (((unsigned) (val >> 24)) << 24) | ((val >> 16 & 0xff) << 16) | ((val >> 8 & 0xff) ) << 8 | (val & 0xff);
  452.             constant_pool[i] = new CONSTANT_Integer_info(CONSTANT_Integer, bytes);
  453.         }
  454.  
  455.         return index;
  456.     }
  457.  
  458.  
  459.     u2 FindInteger(IntLiteralValue *lit)
  460.     {
  461.         return (lit && integer_constant_pool_index ? (*integer_constant_pool_index)[lit -> index] : 0);
  462.     }
  463.  
  464.  
  465.     u2 RegisterLong(LongLiteralValue *lit)
  466.     {
  467.         assert((lit != NULL) && "null argument to RegisterLong");
  468.  
  469.         if (! long_constant_pool_index)
  470.             long_constant_pool_index = new Pair(segment_pool, this_control.long_pool.symbol_pool.Length());
  471.  
  472.         u2 index = (*long_constant_pool_index)[lit -> index];
  473.         if (index == 0)
  474.         {
  475.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  476.             constant_pool.Next() = NULL;       // extra slop for double-word entry
  477.             index = i;
  478.             (*long_constant_pool_index)[lit -> index] = index;
  479.             constant_pool[i] = new CONSTANT_Long_info(CONSTANT_Long, lit -> value.HighWord(), lit -> value.LowWord());
  480.         }
  481.  
  482.         return index;
  483.     }
  484.  
  485.  
  486.     u2 RegisterFloat(FloatLiteralValue *lit)
  487.     {
  488.         assert((lit != NULL) && "null argument to RegisterFloat");
  489.  
  490.         if (! float_constant_pool_index)
  491.             float_constant_pool_index = new Pair(segment_pool, this_control.float_pool.symbol_pool.Length());
  492.  
  493.         u2 index = (*float_constant_pool_index)[lit -> index];
  494.         if (index == 0)
  495.         {
  496.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  497.             index = i;
  498.             (*float_constant_pool_index)[lit -> index] = index;
  499.             constant_pool[i] = new CONSTANT_Float_info(CONSTANT_Float, lit -> value.Word());
  500.         }
  501.  
  502.         return index;
  503.     }
  504.  
  505.  
  506.     u2 RegisterUtf8(Utf8LiteralValue *lit)
  507.     {
  508.         assert((lit != NULL) && "null argument to RegisterUtf8");
  509.  
  510.         u2 index = utf8_constant_pool_index[lit -> index];
  511.         if (index == 0)
  512.         {
  513.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  514.             index = i;
  515.             utf8_constant_pool_index[lit -> index] = index;
  516.             constant_pool[i] = new CONSTANT_Utf8_info(CONSTANT_Utf8, lit -> value, lit -> length);
  517.         }
  518.  
  519.         return index;
  520.     }
  521.  
  522.  
  523.     u2 RegisterString(Utf8LiteralValue *lit)
  524.     {
  525.         assert((lit != NULL) && "null argument to RegisterString");
  526.  
  527.         //
  528.         // The domain of these maps is an index in the constant_pool.
  529.         // For a valid program, the size of the constant pool is limited
  530.         // to 65k elements.
  531.         //
  532.         if (! string_constant_pool_index)
  533.             string_constant_pool_index = new Pair(segment_pool, this_control.Utf8_pool.symbol_pool.Length());
  534.  
  535.         u2 index = (*string_constant_pool_index)[lit -> index];
  536.         if (index == 0)
  537.         {
  538.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  539.             index = i;
  540.             (*string_constant_pool_index)[lit -> index] = index;
  541.             constant_pool[i] = new CONSTANT_String_info(CONSTANT_String, RegisterUtf8(lit));
  542.         }
  543.  
  544.         return index;
  545.     }
  546.  
  547.  
  548.     u2 RegisterClass(Utf8LiteralValue *lit)
  549.     {
  550.         assert((lit != NULL) && "null argument to RegisterClass");
  551.  
  552.         u2 index = class_constant_pool_index[lit -> index];
  553.         if (index == 0)
  554.         {
  555.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  556.             index = i;
  557.             class_constant_pool_index[lit -> index] = index;
  558.             constant_pool[i] = new CONSTANT_Class_info(CONSTANT_Class, RegisterUtf8(lit));
  559.         }
  560.  
  561.         return index;
  562.     }
  563.  
  564.  
  565.     //
  566.     //  Methods to write out the byte code
  567.     //
  568.     Deprecated_attribute *CreateDeprecatedAttribute()
  569.     {
  570.         return new Deprecated_attribute(RegisterUtf8(this_control.Deprecated_literal));
  571.     }
  572.  
  573.  
  574.     Synthetic_attribute *CreateSyntheticAttribute()
  575.     {
  576.         return new Synthetic_attribute(RegisterUtf8(this_control.Synthetic_literal));
  577.     }
  578.  
  579.  
  580.     //
  581.     // Methods to generate expressions.
  582.     //
  583.     int  EmitExpression(AstExpression *);
  584.     int  EmitArrayCreationExpression(AstArrayCreationExpression *);
  585.     int  EmitAssignmentExpression(AstAssignmentExpression *, bool);
  586.     int  EmitBinaryExpression(AstBinaryExpression *);
  587.     int  EmitCastExpression(AstCastExpression *);
  588.     void EmitCast(TypeSymbol *, TypeSymbol *);
  589.     int  EmitClassInstanceCreationExpression(AstClassInstanceCreationExpression *, bool);
  590.     int  EmitConditionalExpression(AstConditionalExpression *);
  591.     int  EmitFieldAccess(AstFieldAccess *);
  592.     AstExpression *VariableExpressionResolution(AstExpression *);
  593.     TypeSymbol *VariableTypeResolution(AstExpression *, VariableSymbol *);
  594.     TypeSymbol *MethodTypeResolution(AstExpression *, MethodSymbol *);
  595.     void EmitFieldAccessLhsBase(AstExpression *);
  596.     void EmitFieldAccessLhs(AstExpression *);
  597.     void EmitMethodInvocation(AstMethodInvocation *);
  598.     void EmitNewArray(int, TypeSymbol *);
  599.     int  EmitPostUnaryExpression(AstPostUnaryExpression *, bool);
  600.     void EmitPostUnaryExpressionArray(AstPostUnaryExpression *, bool);
  601.     void EmitPostUnaryExpressionField(int, AstPostUnaryExpression *, bool);
  602.     void EmitPostUnaryExpressionSimple(int, AstPostUnaryExpression *, bool);
  603.     int  EmitPreUnaryExpression(AstPreUnaryExpression *, bool);
  604.     void EmitPreUnaryIncrementExpression(AstPreUnaryExpression *expression, bool);
  605.     void EmitPreUnaryIncrementExpressionArray(AstPreUnaryExpression *expression, bool);
  606.     void EmitPreUnaryIncrementExpressionField(int, AstPreUnaryExpression *expression, bool);
  607.     void EmitPreUnaryIncrementExpressionSimple(int, AstPreUnaryExpression *expression, bool);
  608.     void EmitThisInvocation(AstThisCall *);
  609.     void EmitSuperInvocation(AstSuperCall *);
  610.     void ConcatenateString(AstBinaryExpression *);
  611.     void AppendString(AstExpression *);
  612.     void EmitStringAppendMethod(TypeSymbol *);
  613.     void GenerateAccessMethod(MethodSymbol *);
  614.     void ChangeStack (int);
  615.     void ResolveAccess(AstExpression *);
  616.     int  GenerateClassAccess(AstFieldAccess *);
  617.     void GenerateClassAccessMethod(MethodSymbol *);
  618.  
  619.     //
  620.     // Methods to process statements
  621.     //
  622.     void CompileConstructor(AstConstructorDeclaration *, Tuple<AstVariableDeclarator *> &);
  623.  
  624.     void BeginMethod(int, MethodSymbol *);
  625.     void EndMethod(int, MethodSymbol *);
  626.     void DeclareField(VariableSymbol *);
  627.     void InitializeClassVariable(AstVariableDeclarator *);
  628.     void InitializeInstanceVariable(AstVariableDeclarator *);
  629.     void InitializeArray(TypeSymbol *, AstArrayInitializer *);
  630.     void DeclareLocalVariable(AstVariableDeclarator *);
  631.     void EmitStatement(AstStatement *);
  632.     void EmitReturnStatement(AstReturnStatement *);
  633.     void EmitSynchronizedStatement(AstSynchronizedStatement *);
  634.     void EmitBlockStatement(AstBlock *, bool);
  635.     void EmitStatementExpression(AstExpression *);
  636.     void EmitSwitchStatement(AstSwitchStatement *);
  637.     void UpdateBlockInfo(BlockSymbol *);
  638.     void EmitTryStatement(AstTryStatement *);
  639.     void EmitBranchIfExpression(AstExpression *, bool, Label &);
  640.     void CompleteCall(MethodSymbol *, int, TypeSymbol * = NULL);
  641.  
  642.  
  643.     //
  644.     // called when expression has been parenthesized to removed
  645.     // parantheses and expose true structure.
  646.     //
  647.     AstExpression *UnParenthesize(AstExpression *expr)
  648.     {
  649.         while(expr -> ParenthesizedExpressionCast())
  650.             expr = expr -> ParenthesizedExpressionCast() -> expression;
  651.  
  652.         return expr;
  653.     }
  654.  
  655.  
  656.     void EmitArrayAccessLhs(AstArrayAccess *expression)
  657.     {
  658.         LoadReference(expression -> base);
  659.         EmitExpression(expression -> expression);
  660.  
  661.         return;
  662.     }
  663.  
  664.  
  665.     int EmitArrayAccessRhs(AstArrayAccess *expression)
  666.     {
  667.         EmitArrayAccessLhs(expression); // get array address and index
  668.         return LoadArrayElement(expression -> Type());
  669.     }
  670.  
  671.  
  672.     void EmitBranch(unsigned int opc, Label& lab)
  673.     {
  674.         PutOp(opc);
  675.         UseLabel(lab, 2, 1);
  676.  
  677.         return;
  678.     }
  679.  
  680.  
  681.     void GenerateReturn(TypeSymbol *type)
  682.     {
  683.         PutOp(this_control.IsSimpleIntegerValueType(type) || type == this_control.boolean_type
  684.                   ? OP_IRETURN
  685.                   : type == this_control.long_type
  686.                           ? OP_LRETURN
  687.                           : type == this_control.float_type
  688.                                   ? OP_FRETURN
  689.                                   : type == this_control.double_type
  690.                                           ? OP_DRETURN
  691.                                           : OP_ARETURN);
  692.         return;
  693.     }
  694.  
  695.  
  696. #ifdef TEST
  697.     void PrintCode();
  698. #endif
  699.  
  700.     void PutOp(unsigned char opc);
  701.  
  702.     void PutOpWide(unsigned char opc, u2 var);
  703.  
  704.     void PutOpIINC(u2 var, int val);
  705.  
  706.     //
  707.     //  Methods to insert values into byte code
  708.     //
  709.     void PutI1(i1 i)
  710.     {
  711.         code_attribute -> AddCode(i & 0xff);
  712.  
  713.         return;
  714.     }
  715.  
  716.  
  717.     void PutI2(i2 i)
  718.     {
  719.         code_attribute -> AddCode((i >> 8) & 0xff);
  720.         code_attribute -> AddCode(i & 0xff);
  721.  
  722.         return;
  723.     }
  724.  
  725.  
  726.     void PutU1(u1 u)
  727.     {
  728.         code_attribute -> AddCode(u & 0xff);
  729.  
  730.         return;
  731.     }
  732.  
  733.  
  734.     void PutU2(u2 u)
  735.     {
  736.         code_attribute -> AddCode((u >> 8) & 0xff);
  737.         code_attribute -> AddCode(u & 0xff);
  738.  
  739.         return;
  740.     }
  741.  
  742.  
  743.     void PutU4(u4 u)
  744.     {
  745.         code_attribute -> AddCode((u >> 24));
  746.         code_attribute -> AddCode((u >> 16) & 0xff);
  747.         code_attribute -> AddCode((u >>  8) & 0xff);
  748.         code_attribute -> AddCode(u & 0xff);
  749.  
  750.         return;
  751.     }
  752.  
  753.  
  754.     //
  755.     // emit NOP. The NOP can be replaced by the next instruction if
  756.     // optional is set; otherwise it must be kept.
  757.     //
  758.     void PutNop(int optional)
  759.     {
  760.         PutOp(OP_NOP);
  761.  
  762.         //
  763.         // this optimization is causing more trouble than it's worth.
  764.         // latest problem (27 jan 97) was reported by Derek, in that
  765.         // nop just before label definition, resulted in operation generated
  766.         // after label def. being moved before the def! Since it's such a sin
  767.         // to generate junk code, disable the "nop" optimization.
  768.         //  if (optional) last_op_nop = 1;
  769.         //
  770.  
  771.         return;
  772.     }
  773.  
  774.     void FinishCode(TypeSymbol *);
  775.  
  776.     void Reset()
  777.     {
  778.         constant_pool.Reset();
  779.         fields.Reset();
  780.         methods.Reset();
  781.         attributes.Reset();
  782.         this_class = super_class = 0;
  783.     }
  784.  
  785. public:
  786.     ByteCode(TypeSymbol *);
  787.  
  788.     ~ByteCode()
  789.     {
  790.         delete double_constant_pool_index;
  791.         delete integer_constant_pool_index;
  792.         delete long_constant_pool_index;
  793.         delete float_constant_pool_index;
  794.         delete string_constant_pool_index;
  795.  
  796.         delete name_and_type_constant_pool_index;
  797.         delete fieldref_constant_pool_index;
  798.         delete methodref_constant_pool_index;
  799.     }
  800.  
  801.     inline void GenerateCode()
  802.     {
  803.         if (unit_type -> ACC_INTERFACE())
  804.              CompileInterface();
  805.         else CompileClass();
  806.     }
  807. };
  808.  
  809. #endif
  810.